package com.yvan.leto;

import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.yvan.leto.api.ConfigApi;
import com.yvan.leto.reg.ConfigRegistry;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;

import java.util.List;
import java.util.concurrent.ConcurrentMap;

@Slf4j
public class LetoManage {

    static final ConcurrentMap<String, String> CACHE = Maps.newConcurrentMap();

    private final AppConfig appConfig;
    private final ConfigRegistry configRegistry;
    private final ConfigApi configApi;

    private final List<ConfigListener> listeners = Lists.newCopyOnWriteArrayList();

    final SpringApplication springApplication;

    public <T> LetoManage(Class<T> clazz) {
        this.springApplication = new SpringApplication(clazz);

        appConfig = new AppConfig(clazz);
        configApi = new ConfigApi(appConfig.letoServer);
        configRegistry = new ConfigRegistry();
    }

    public void addListener(ConfigListener listener) {
        listener.setup(this);
        listeners.add(listener);
    }

    private void applySegment(ConfigListener listener) {
        final String segmentName = listener.watchSegment();
        listener.onChange(new ConfigChangeEvent(segmentName, getSegmentContent(segmentName)));
    }

    /**
     * 读取配置文件
     */
    public String getSegmentContent(final String segment) {
        return CACHE.computeIfAbsent(segment, k ->
                configApi.getSegmentContent(appConfig.env, appConfig.appId, segment)
        );
    }

    public void run(String[] args) {
        log.info("leto config init ...");
        appConfig.loadArgs(args);

        log.info("leto app={}, env={}, letoServer={}, clientId={}",
                appConfig.appId,
                Sets.newLinkedHashSet(Splitter.on(",").omitEmptyStrings().split(appConfig.env)),
                appConfig.letoServer,
                appConfig.clientId);

        //初始化 segments
        for (ConfigListener listener : listeners) {
            applySegment(listener);
        }

        springApplication.run(args);
    }
}
